package com.ntd.study.pro.zx.wlpt;

import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.URL;

/**
 * testClient
 *
 * @param :${params}
 * @author :
 * @date :2019-02-15 下午10:13
 */
public class TestClient {

    private static TestClient instance = new TestClient();

    private TestClient() {}

    public static TestClient getInstance() {
        return instance;
    }

    public byte[] TestServer(String url, String trustStoreJksFileName, byte[] reqPostData) throws IOException {
        String serverIP;
        int serverPort = 443;
        URL u = new URL(url);
        serverIP = u.getHost();
        if (u.getPort() != -1) {
            serverPort = u.getPort();
        }

        System.setProperty("javax.net.ssl.trustStore", trustStoreJksFileName);
        System.setProperty("javax.net.ssl.trustStorePassword", "123456");
        System.setProperty("javax.net.ssl.trustStoreType", "JKS");
        // Getting the default SSL socket factory
        SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
        System.out.println("The default SSL socket factory class: " + f.getClass());
        OutputStream os;
        byte[] respPostData = null;
        try {
            // Getting the default SSL socket factory
            SSLSocket c = (SSLSocket) f.createSocket(serverIP, serverPort);

            printSocketInfo(c);
            c.startHandshake();
            BufferedWriter w = new BufferedWriter(new OutputStreamWriter(c.getOutputStream()));
            BufferedReader r = new BufferedReader(new InputStreamReader(c.getInputStream()));
            os = c.getOutputStream();
            StringBuilder buffer = new StringBuilder();
             buffer.append("POST ").append(url).append(" HTTP/1.1\r\n");
            buffer.append("User-Agent: Java/1.6\r\n");
            buffer.append("Host: ").append(serverIP).append("\r\n");
            buffer.append("Content-Type: text/plain; charset=GBK\r\n");
            if (reqPostData == null || reqPostData.length == 0) {
                buffer.append("Content-Length: 0\r\n");
            } else {
                buffer.append("Content-Length: ").append(reqPostData.length).append("\r\n");
            }
            buffer.append("\r\n");
            System.out.println("--- Sending request headers:");
            CommonUtils.dump(">> ", buffer.toString());

            w.write(buffer.toString());
            w.flush();
            if (reqPostData != null && reqPostData.length > 0) {
                System.out.println("--- Sending request body data:");
                CommonUtils.dump(">> ", reqPostData);
                os.write(reqPostData);
                os.flush();
            }

            InputStream is = c.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);

            String line;

            System.out.println("--- Receiving response:");

            int postDataLen = -1;
            while ((line = CommonUtils.streamReadLineDump(is)) != null) {
                if (line.length() == 0) {
                    break;
                }
                if (line.contains("Content-Length:")) {
                    postDataLen = new Integer(line.substring(line.indexOf("Content-Length:") + 16, line.length()));
                }
            }

            if (postDataLen > 0) {
                int totalBytesRead = 0;
                respPostData = new byte[postDataLen];
                while (totalBytesRead < postDataLen) {
                    int bytesRemaining = postDataLen - totalBytesRead;
                    int bytesRead = bis.read(respPostData, totalBytesRead, bytesRemaining);
                    if (bytesRead == -1) {
                        break; // socket has been closed
                    }
                    totalBytesRead += bytesRead;
                }
                if (totalBytesRead > 0) {
                    CommonUtils.dump("<< ", respPostData, 0, totalBytesRead);
                }
                if (totalBytesRead < postDataLen) {
                    System.out.println("读取信息不完整：totalBytesRead=" + totalBytesRead + ", postDataLen =" + postDataLen);
                } else {
                    System.out.println("recv resp:【" + new String(respPostData) + "】");
                }
            }
            w.close();
            r.close();
            c.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return respPostData;
    }

    private static void printSocketInfo(SSLSocket s) {
        System.out.println("Socket class: " + s.getClass());
        System.out.println("   Remote address = " + s.getInetAddress().toString());
        System.out.println("   Remote port = " + s.getPort());
        System.out.println("   Local socket address = " + s.getLocalSocketAddress().toString());
        System.out.println("   Local address = " + s.getLocalAddress().toString());
        System.out.println("   Local port = " + s.getLocalPort());
        System.out.println("   Need client authentication = " + s.getNeedClientAuth());
        SSLSession ss = s.getSession();
        System.out.println("   Cipher suite = " + ss.getCipherSuite());
        System.out.println("   Protocol = " + ss.getProtocol());
    }

}
